const express = require('express');
const app = express();
const http = require('http').createServer(app);
const cors = require('cors');
const mongoose = require('mongoose');
const path = require('path');
const config = require('./config/config');

const io = require('socket.io')(http, {
    cors: {
        origin: config.allowedOrigins,
        methods: ["GET", "POST"],
        credentials: true
    }
});

// 导入路由
const authRoutes = require('./routes/auth');
const uploadRoutes = require('./routes/upload');

// 导入模型
const Message = require('./models/Message');
const User = require('./models/User');

// 连接MongoDB
mongoose.connect(config.mongoUri)
    .then(() => console.log('MongoDB连接成功'))
    .catch(err => console.error('MongoDB连接失败:', err));

// 配置CORS中间件
app.use(cors({
    origin: function(origin, callback) {
        if (!origin || config.allowedOrigins.indexOf(origin) !== -1) {
            callback(null, true);
        } else {
            callback(new Error('不允许的来源'));
        }
    },
    methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
    allowedHeaders: ['Content-Type', 'Authorization'],
    credentials: true,
    optionsSuccessStatus: 200
}));

// 配置其他中间件
app.use(express.json());
app.use('/uploads', express.static(path.join(__dirname, '..', config.uploadDir)));
app.use('/node_modules', express.static(path.join(__dirname, '../../client/web/node_modules')));
app.use(express.static(path.join(__dirname, '../../client/web/src')));

// 配置路由
app.use('/auth', authRoutes);
app.use('/upload', uploadRoutes);

// Socket.IO 事件处理
io.on('connection', async (socket) => {
    console.log('新用户连接');
    
    // 用户加入
    socket.on('user_join', async (username) => {
        try {
            // 创建或更新用户
            let user = await User.findOne({ username });
            if (!user) {
                user = new User({ username });
            }
            user.socketId = socket.id;
            user.status = 'online';
            user.lastSeen = new Date();
            await user.save();
            
            console.log(`用户上线: ${username}`);
            
            // 获取在线用户列表
            const onlineUsers = await User.find({ 
                status: 'online',
                username: { $ne: username }
            });
            
            // 发送欢迎消息
            const welcomeMessage = new Message({
                type: 'group',
                from: { userId: 'system', username: 'System' },
                content: `${username} 加入了聊天室`,
            });
            await welcomeMessage.save();

            // 获取用户的未读消息
            const unreadMessages = user.unreadMessages;
            if (unreadMessages.length > 0) {
                const fullMessages = await Message.find({
                    _id: { $in: unreadMessages.map(m => m.messageId) }
                }).sort({ createdAt: 1 });

                socket.emit('unread_messages', fullMessages);

                user.unreadMessages = [];
                await user.save();
            }

            // 广播用户加入消息
            const allOnlineUsers = [...onlineUsers, user].map(u => ({
                userId: u.socketId,
                username: u.username,
                status: u.status
            }));

            io.emit('user_joined', {
                userId: socket.id,
                username: username,
                onlineUsers: allOnlineUsers
            });

            // 发送历史消息
            const history = await Message.find({
                $or: [
                    { type: 'group' },
                    {
                        type: 'private',
                        $or: [
                            { 'from.username': username },
                            { 'to.username': username }
                        ]
                    }
                ]
            })
            .sort({ createdAt: -1 })
            .limit(50);

            socket.emit('message_history', history.reverse());
            
        } catch (error) {
            console.error('用户加入错误:', error);
        }
    });
    
    // 群聊消息
    socket.on('chat_message', async (data) => {
        try {
            const user = await User.findOne({ socketId: socket.id });
            if (!user) return;

            const message = new Message({
                type: 'group',
                from: {
                    userId: socket.id,
                    username: user.username
                },
                content: data.message,
                file: data.file,
                readBy: [{
                    userId: socket.id,
                    username: user.username,
                    readAt: new Date()
                }]
            });
            await message.save();

            // 为离线用户添加未读消息
            const offlineUsers = await User.find({ 
                status: { $in: ['offline', 'away'] }
            });

            const updates = offlineUsers.map(offlineUser => {
                const unreadMessage = {
                    messageId: message._id.toString(),
                    fromUserId: socket.id,
                    fromUsername: user.username,
                    type: 'group',
                    timestamp: new Date()
                };
                return User.updateOne(
                    { _id: offlineUser._id },
                    { $push: { unreadMessages: unreadMessage } }
                );
            });

            await Promise.all(updates);
            
            // 广播消息给所有用户
            io.emit('chat_message', {
                messageId: message._id,
                type: 'group',
                from: {
                    userId: socket.id,
                    username: user.username
                },
                content: data.message,
                file: data.file,
                timestamp: message.createdAt,
                readBy: message.readBy
            });
            
        } catch (error) {
            console.error('发送消息错误:', error);
        }
    });
    
    // 私聊消息
    socket.on('private_message', async (data) => {
        try {
            const user = await User.findOne({ socketId: socket.id });
            if (!user) return;

            const toUser = await User.findOne({ socketId: data.to });
            if (!toUser) return;

            const message = new Message({
                type: 'private',
                from: {
                    userId: socket.id,
                    username: user.username
                },
                to: {
                    userId: toUser.socketId,
                    username: toUser.username
                },
                content: data.message,
                file: data.file,
                readBy: [{
                    userId: socket.id,
                    username: user.username,
                    readAt: new Date()
                }]
            });
            await message.save();
            
            // 如果接收者离线，添加到未读消息
            if (toUser.status === 'offline' || toUser.status === 'away') {
                const unreadMessage = {
                    messageId: message._id.toString(),
                    fromUserId: socket.id,
                    fromUsername: user.username,
                    type: 'private',
                    timestamp: new Date()
                };
                await User.updateOne(
                    { _id: toUser._id },
                    { $push: { unreadMessages: unreadMessage } }
                );
            }

            // 发送给发送者
            socket.emit('private_message', {
                messageId: message._id,
                type: 'private',
                from: {
                    userId: socket.id,
                    username: user.username
                },
                to: {
                    userId: toUser.socketId,
                    username: toUser.username
                },
                content: data.message,
                file: data.file,
                timestamp: message.createdAt,
                readBy: message.readBy,
                sent: true
            });

            // 发送给接收者
            io.to(toUser.socketId).emit('private_message', {
                messageId: message._id,
                type: 'private',
                from: {
                    userId: socket.id,
                    username: user.username
                },
                content: data.message,
                file: data.file,
                timestamp: message.createdAt,
                readBy: message.readBy,
                sent: false
            });
            
        } catch (error) {
            console.error('发送私聊消息错误:', error);
        }
    });
    
    // 处理消息已读状态
    socket.on('message_read', async (data) => {
        try {
            const user = await User.findOne({ socketId: socket.id });
            if (!user) return;
            
            const message = await Message.findById(data.messageId);
            if (!message) return;
            
            // 检查是否已经标记为已读
            const alreadyRead = message.readBy.some(r => r.userId === socket.id);
            if (!alreadyRead) {
                message.readBy.push({
                    userId: socket.id,
                    username: user.username,
                    readAt: new Date()
                });
                await message.save();
                
                // 广播消息已读状态
                io.emit('message_read_status', {
                    messageId: message._id,
                    readBy: message.readBy
                });
            }
        } catch (error) {
            console.error('更新消息已读状态错误:', error);
        }
    });
    
    // 处理用户状态更新
    socket.on('update_status', async (status) => {
        try {
            const user = await User.findOne({ socketId: socket.id });
            if (!user) return;

            user.status = status;
            user.lastSeen = new Date();
            await user.save();

            // 获取所有在线用户
            const onlineUsers = await User.find({ status: 'online' });
            const usersList = onlineUsers.map(u => ({
                userId: u.socketId,
                username: u.username,
                status: u.status
            }));

            // 广播用户状态变化
            io.emit('user_status_changed', {
                userId: socket.id,
                username: user.username,
                status: status,
                onlineUsers: usersList
            });
        } catch (error) {
            console.error('更新用户状态错误:', error);
        }
    });

    // 处理用户断开连接
    socket.on('disconnect', async () => {
        try {
            const user = await User.findOne({ socketId: socket.id });
            if (!user) return;

            user.status = 'offline';
            user.lastSeen = new Date();
            await user.save();

            // 获取所有在线用户
            const onlineUsers = await User.find({ status: 'online' });
            const usersList = onlineUsers.map(u => ({
                userId: u.socketId,
                username: u.username,
                status: u.status
            }));

            // 广播用户离开消息
            io.emit('user_left', {
                userId: socket.id,
                username: user.username,
                onlineUsers: usersList
            });
        } catch (error) {
            console.error('用户断开连接错误:', error);
        }
    });

    // 加载私聊历史记录
    socket.on('load_private_history', async (data) => {
        try {
            const user = await User.findOne({ socketId: socket.id });
            if (!user) return;

            const messages = await Message.find({
                type: 'private',
                $or: [
                    {
                        'from.username': user.username,
                        'to.username': data.withUser
                    },
                    {
                        'from.username': data.withUser,
                        'to.username': user.username
                    }
                ]
            })
            .sort({ createdAt: -1 })
            .limit(50);

            socket.emit('private_history', messages.reverse());
        } catch (error) {
            console.error('加载私聊历史记录错误:', error);
        }
    });

    // 处理消息删除
    socket.on('delete_message', async (data) => {
        try {
            const user = await User.findOne({ socketId: socket.id });
            if (!user) return;
            
            const message = await Message.findById(data.messageId);
            if (!message) return;
            
            // 只允许消息发送者删除消息
            if (message.from.username === user.username) {
                message.isDeleted = true;
                message.deletedBy = {
                    userId: socket.id,
                    username: user.username,
                    deletedAt: new Date()
                };
                await message.save();
                
                // 广播消息删除事件
                io.emit('message_deleted', {
                    messageId: message._id,
                    deletedBy: message.deletedBy
                });
            }
        } catch (error) {
            console.error('删除消息错误:', error);
        }
    });
});

// 启动服务器
http.listen(config.port, () => {
    console.log(`服务器运行在端口 ${config.port}`);
}); 